#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    Init();
    //开启串口线程
    comThread = new uartWork();
    comThread->startThread();
    uartIsOpen = false;

    //串口绑定信号槽
    connect(comThread, &uartWork::readyread, this, &MainWindow::readFromCom,
            Qt::QueuedConnection);
    connect(comThread, &uartWork::openError, this, &MainWindow::openSucess,
            Qt::QueuedConnection);
    connect(comThread, &uartWork::errOccurred, this, &MainWindow::errorOccurred,
            Qt::QueuedConnection);
    connect(this,&MainWindow::sendData2Uart, comThread, &uartWork::writeData,
            Qt::QueuedConnection);
    connect(this, &MainWindow::upCfg2Uart, comThread, &uartWork::updateComCfg,
            Qt::QueuedConnection);
    connect(this, &MainWindow::closeUart, comThread, &uartWork::stopThread,
            Qt::QueuedConnection);
}
void MainWindow::Init()
{
    //读取串口信息
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        // 自动读取串口号添加到端口portBox中
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->ser_port_name->addItem(info.portName());
            serial.close();
        }
    }
    //表格初始化
    table_dataInit();
    //显示当前时间
    m_timer = new QTimer(this);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(timerShow()));
    m_timer->setInterval(1000);
    m_timer->start();

    m_resendtimer = new QTimer(this);
    connect(m_resendtimer, SIGNAL(timeout()), this, SLOT(resendShow()));
    m_resendtimer->setInterval(3000);
    m_msg_dialog = new msgDialog(this);
    //
    //创建报文封装类对象
    mb_msg = new Modbusmsg;
    connect(this,&MainWindow::ParseResponseMessage,mb_msg,&Modbusmsg::ParseResponseMessage,
            Qt::QueuedConnection);
    connect(this,&MainWindow::packageSartc,mb_msg,&Modbusmsg::packageSartc,
            Qt::QueuedConnection);
    connect(this,&MainWindow::packageSartr,mb_msg,&Modbusmsg::packageSartr,
            Qt::QueuedConnection);
    connect(mb_msg,&Modbusmsg::package_over,this,m_SendMsg);
    connect(mb_msg,&Modbusmsg::showMsgtoUi,this,showMsg);
    connect(mb_msg,&Modbusmsg::showlogmsg,this,showlogmsg);
    connect(mb_msg,&Modbusmsg::wirtTablec,this,&MainWindow::wirtTablec);
    connect(mb_msg,&Modbusmsg::wirtTabler,this,&MainWindow::wirtTabler);

    readseting = new QSettings("dataini/Data.ini", QSettings::IniFormat);
    ReadOutIniData();
    qDebug()<<"主线程:"<<QThread::currentThreadId();
}
MainWindow::~MainWindow()
{
    delete ui;
    delete m_timer;
    delete m_resendtimer;
    delete mb_msg;
    delete m_msg_dialog;
    delete readseting;
}
//获取串口读取到的数据
void MainWindow::readFromCom(QByteArray disData)
{
    uartSrcData = disData;
    if(sendflag)
    {

        if(disData.isEmpty()==true)
        {
            qDebug() <<"没有数据！";
        }
        else
        {
            m_resendtimer->stop();
            resendNumber=0;
            emit ParseResponseMessage(disData);
            sendflag = false;
        }
    }
    else
    {
      disData.clear();
    }
}
//发送消息槽
void MainWindow::m_SendMsg(QByteArray ba)
{
    QString s;
    //串口发送
    if(uartIsOpen)
    {
        resenddata = ba;
        emit sendData2Uart(ba);
        sendflag = true;
    }
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
    ByteToHexString(s,ba);
    ui->recv_Edit->append(current_date+"\n发送查询报文:--->\r\n"+s);
    ui->recv_Edit->moveCursor(QTextCursor::End);
    m_resendtimer->start();
}
//发送数据
void MainWindow::on_send_msg_clicked()
{
    //串口发送
    if(uartIsOpen)
    {
        //调用封装类封装数据并发送
        switch(m_code)
        {
        case 1:
            if(checkUserInputData())
            {
                emit packageSartr(inf.at(0),1,inf.at(1),inf.at(2));
            }
            else
            {
                QMessageBox::warning(this,"错误","还未设置数据！");
            }
            break;
        case 3:
            if(checkUserInputData())
            {
                emit packageSartr(inf.at(0),3,inf.at(1),inf.at(2));
            }
            else
            {
                QMessageBox::warning(this,"错误","还未设置数据！");
            }
            break;
        case 15:
            if(!coildata.isEmpty())
            {
                emit packageSartc(inf.at(0),15,inf.at(1),inf.at(2),coildata,regdata);
            }
            else
            {
                QMessageBox::warning(this,"错误","还未设置数据！");
            }
            break;
        case 16:
            if(!regdata.isEmpty())
            {
                emit packageSartc(inf.at(0),16,inf.at(1),inf.at(2),coildata,regdata);
            }
            else
            {
                QMessageBox::warning(this,"错误","还未设置数据！");
            }
            break;
        default:
            QMessageBox::warning(this,"错误","还未设置数据！");
            break;
        }
    }
    else
    {
        QMessageBox::warning(this,"错误","还未打开串口！");
    }
}
//二次检测地址，起始地址，数量用户输入数据是否为空
bool MainWindow::checkUserInputData()
{
    if(inf.isEmpty()||(inf.at(0)==0)||(inf.at(2)==0))
    {
        return false;
    }
    else
    {
        return true;
    }
}
//二次检测用户写操作数据是否为空
bool MainWindow::checkUserInputWirteData()
{
    if(!checkUserInputData())
    {
        return false;
    }
    else
    {
        return true;
    }
}
//显示log信息
void MainWindow::showlogmsg(QString msg)
{

    ui->recv_Edit->append(msg+"\r\n");
}
//超时重发
void MainWindow::resendShow()
{
    resendNumber++;
    if(resendNumber<4)
    {
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
        ui->recv_Edit->append(current_date+"从站无响应！");
        ui->recv_Edit->append("已向目标从站第"
                              + QString::number(resendNumber)
                              + "次重新发送报文\n");
       emit sendData2Uart(resenddata);
    }
    else
    {
        resendNumber=0;
        ui->recv_Edit->append("3次重传无效，从站无响应!\n");
        m_resendtimer->stop();
    }
}
//01功能码读线圈
void MainWindow::on_r_coil_clicked()
{
    m_0103dialog = new userInput0103Dialog(this);
    m_code = 0x01;
    m_0103dialog->setNumLimited("1-2000");
    int flag =  m_0103dialog->exec();
    if(!flag)
    {
        inf = m_0103dialog->infdata();
    }
    delete m_0103dialog;
}
//03功能码读寄存器
void MainWindow::on_r_regs_clicked()
{
    m_0103dialog = new userInput0103Dialog(this);
    m_code = 0x03;
    m_0103dialog->setNumLimited("1-125");
    int flag =  m_0103dialog->exec();
    if(!flag)
    {
        inf = m_0103dialog->infdata();
    }
    delete m_0103dialog;
}
//0f功能码写线圈
void MainWindow::on_w_coil_clicked()
{
    m_0fdialog = new userInputDialog0f(this);
    m_code = 0x0f;
    int flag =  m_0fdialog->exec();
    if(!flag)
    {
        inf = m_0fdialog->infdata();
        coildata = m_0fdialog->getUserInputData();
    }
    delete m_0fdialog;
}
//10功能码写寄存器
void MainWindow::on_w_regs_clicked()
{
    m_10dialog = new userInputDialog10(this);
    m_code = 0x10;
    int flag =  m_10dialog->exec();
    if(!flag)
    {
        inf = m_10dialog->infdata();
        regdata = m_10dialog->getUserInputData();
    }
    delete m_10dialog;
}
//开启关闭串口
void MainWindow::on_ser_concent_clicked()
{
    // 打开串口
    if (uartIsOpen)
    {
        ui->ser_concent->setText("打开");
        if(judgement("是否关闭串口？"))
        {
            ui->ser_concent->setText("打开");
            emit closeUart();
        }
    }
    else
    {

        ui->ser_concent->setText("关闭");
        res_config.portNum =ui->ser_port_name->currentText();
        res_config.baudRate =ui->bround_->currentText().toInt();
        res_config.dataBits =(QSerialPort::DataBits)(ui->data_bit->currentText().toInt());
        if(ui->check_code_bit->currentText()=="奇校验")
        {
            res_config.paritys =QSerialPort::OddParity;
        }
        else if(ui->check_code_bit->currentText()=="偶校验")
        {
            res_config.paritys =QSerialPort::EvenParity;
        }
        else if(ui->check_code_bit->currentText()=="无校验")
        {
            res_config.paritys =QSerialPort::NoParity;
        }
        res_config.stopBits =(QSerialPort::StopBits)(ui->stop_bit->currentText().toInt());

#if DEBUG

        qDebug() << "串口号：" << res_config.portNum <<endl;
        qDebug() << "波特率：" << res_config.baudRate <<endl;
        qDebug() << "校验：" << res_config.paritys <<endl;
        qDebug() << "停止位：" << res_config.stopBits <<endl;
        qDebug() << "数据位：" << res_config.dataBits <<endl;

#endif

        if(judgement("是否打开串口？"))
        {
            ui->ser_concent->setText("关闭");
            //发送信号开启串口
            emit upCfg2Uart(res_config);
        }
    }
}
//串口错误处理
void MainWindow::errorOccurred(QString error)
{
    if (false == error.isEmpty())
    {
        QMessageBox::information(this, "串口错误", error);
    }
}
//判断串口标志
void MainWindow::openSucess(bool sucess)
{
    if (sucess == true)
    {

        ui->ser_concent->setText("关闭");
        uartIsOpen = true;
        uartConfigDisTrue();

    } else
    {
        ui->ser_concent->setText("打开");
        uartIsOpen = false;
        uartConfigDisFalse();
    }
}
//刷新串口号
void MainWindow::on_pushButton_clicked()
{
    ui->ser_port_name->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {   //在portBox中显示可用串口
        ui->ser_port_name->addItem(info.portName());
    }
}
//打开串口后禁止配置参数
void MainWindow::uartConfigDisTrue()
{
    ui->ser_port_name->setDisabled(true);
    ui->stop_bit->setDisabled(true);
    ui->check_code_bit->setDisabled(true);
    ui->data_bit->setDisabled(true);
    ui->bround_->setDisabled(true);
}
//关闭串口后启动配置参数
void MainWindow::uartConfigDisFalse()
{
    ui->ser_port_name->setDisabled(false);
    ui->stop_bit->setDisabled(false);
    ui->check_code_bit->setDisabled(false);
    ui->data_bit->setDisabled(false);
    ui->bround_->setDisabled(false);
}
//显示消息
void MainWindow::showMsg(QString msg)
{
    ui->recv_Edit->append(msg);
}
//当前时间槽
void MainWindow::timerShow()
{
    QDateTime current_date_time =QDateTime::currentDateTime();
    QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss ddd");
    ui->time_line->setText(current_date);
}
//清空窗口
void MainWindow::on_clear_btn_clicked()
{
    if(judgement("是否清除窗口？"))
    {
        ui->recv_Edit->clear();
    }
}
//询问判断
bool MainWindow::judgement(QString msg)
{
    QMessageBox::StandardButton close;
    close = QMessageBox::question(this,"提示",msg,QMessageBox::Yes | QMessageBox::No,QMessageBox::No);

    if(close == QMessageBox::Yes)
    {
        return true;
    }
    else
    {
        return false;
    }
}
//写消息到文件
void MainWindow::on_check_history_clicked()
{
    QString msg =ui->recv_Edit->toPlainText();
    wirteQStringtoTxt(msg);
}
//写入文件
bool MainWindow::wirteQStringtoTxt(QString msg)
{
    QString path = QFileDialog::getOpenFileName(this,"open","./","TXT(*.txt)");
    if(path.isEmpty() == false)
    {

        QMessageBox::information(this,"文件","选择路径成功！");
        //文件对象
        file = new QFile(path);

        //打开文件
        if(file->open(QIODevice::ReadWrite |QIODevice::Text)){

            QTextStream wstream(file);
            QTextStream rstream(file);
            wstream<<msg<<"\n";
            QString showmsg;
            showmsg = rstream.readAll();
            QMessageBox::information(this,"文件","写入成功！");
            file->close();
            delete file;
            m_msg_dialog->setMsg(showmsg);
            m_msg_dialog->show();
            return true;
        }
        else
        {
            QMessageBox::information(this,"文件","失败！");
            return false;
        }

    }
    else
    {
        QMessageBox::information(this,"文件","选择路径失败！");
        return false;
    }
    file->close();
    delete file;
}
//关闭程序事件
void MainWindow::closeEvent(QCloseEvent *event)
{
    if(judgement("确认退出程序？"))
    {
        //关闭界面，保存日志
        QString msg =ui->recv_Edit->toPlainText();
        wirteQStringtoTxt(msg);
        event->accept();
    }
    else
    {
        event->ignore();
    }
}
//表格初始化
void MainWindow::table_dataInit()
{
    //设置表格
    QStringList TableHeader;
    TableHeader << "地址" << "数据";
    ui->table_coil->setVerticalHeaderLabels(TableHeader);
    ui->table_coil->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setVerticalHeaderLabels(TableHeader);
    ui->tableregs->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->tableregs->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->table_coil->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
//将ini文件中的数据放到对应的表格中
void MainWindow::ReadOutIniData(void)
{
    for(int i = 0; i < (ADDRESS_MAX + 1); i++)
    {
        //地址设置
        QString adr =  "0x" + QString("%1").arg(i,4,16,QLatin1Char('0'));
        ui->table_coil->setItem(0,i, new QTableWidgetItem(QString(adr).toUpper()));
        ui->table_coil->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        ui->tableregs->setItem(0,i, new QTableWidgetItem(QString(adr)));
        ui->tableregs->item(0,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //读出线圈数据
        QString coilData = readseting->value("Section" + QString::number(i+1) + "/coil").toString();
        //读出寄存器数据
        QString registerData = readseting->value("Section" + QString::number(i+1) + "/regi").toString();
        //在线圈数据表中显示数据
        ui->table_coil->setItem(1,i,new QTableWidgetItem(coilData));
        //设置表格内文字水平+垂直对齐
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //在寄存器数据表中显示数据
        ui->tableregs->setItem(1,i,new QTableWidgetItem(registerData));
        //设置表格内文字水平+垂直对齐
        ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
}
//更新寄存器表
void MainWindow::wirtTabler(quint16 num, quint16 satrtaddr,QVector<quint16> bar)
{
    ui->tableregs->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
      ui->tableregs->setItem(1,i,new QTableWidgetItem(QString("%1").arg(bar[k])));
      ui->tableregs->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->tableregs->blockSignals(false);
    bar.clear();
}
//更新线圈表
void MainWindow::wirtTablec(quint16 num, quint16 satrtaddr,QString bac)
{
    ui->table_coil->blockSignals(true);
    for(int i = satrtaddr,k=0; k < num;k++,i++)
    {
        //在线圈数据表中显示数据
        QString data;
        if(bac[k] == '1')
        {
            data ="1";
        }
        else
        {
            data ="0";
        }
        ui->table_coil->setItem(1,i,new QTableWidgetItem(data));
        ui->table_coil->item(1,i)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    }
    ui->table_coil->blockSignals(false);
    bac.clear();
}
//查找
void MainWindow::on_check_clicked()
{
    int satrtaddr = ui->startaddr->text().toInt(NULL,10);
    if(bar_indexs==0)
    {
        if(satrtaddr>65535||satrtaddr<0)
        {
            QMessageBox::warning(this,"错误","起始地址超出范围，请重新输入!");
        }
        else
        {
            ReadOutIniDatac(satrtaddr);
        }
    }
    else if(bar_indexs==1)
    {
        if(satrtaddr>65535||satrtaddr<0)
        {
            QMessageBox::warning(this,"错误","起始地址超出范围，请重新输入!");
        }
        else
        {
            ReadOutIniDatar(satrtaddr);
        }
    }
}
//切换tab表格
void MainWindow::on_tabWidget_tabBarClicked(int index)
{
    switch(index){

    case 0 :bar_indexs=0;
        break;
    case 1 :bar_indexs=1;
        break;
    default:
        break;
    }
}
//定位到线圈表指定位置
void MainWindow::ReadOutIniDatac(int start)
{
    QTableWidgetItem* item = ui->table_coil->item(0,start);
    ui->table_coil->setCurrentItem(item);
    ui->table_coil->scrollToItem(item,QAbstractItemView::PositionAtCenter);
}
//定位到寄存器表指定位置
void MainWindow::ReadOutIniDatar(int start)
{
    QTableWidgetItem* item = ui->tableregs->item(0,start);
    ui->tableregs->setCurrentItem(item);
    ui->tableregs->scrollToItem(item,QAbstractItemView::PositionAtCenter);
}
